package com.zf.rabbitmq.producer.dead_letter;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 死信队列
 * <p>
 * 借助 TTL + 死信队列 实现延迟消息：给消息或者队列设置TTL，消息过期后被投递到死信队列，我们消费死信队列就实现了消息的延迟消费，TTL就是延迟时间。
 * 使用 借助 TTL + 死信队列 实现延迟消息的优缺点见 rabbitmq-sample\readme.md
 */
@Component
public class DeadLetterByTtlConfig implements InitializingBean {
    public static final String testTtlQueueExchangeName = "test_ttl_queue_exchange";
    public static final String testTtlQueueRouteKey = "test_ttl_queue_route_key";
    public static final String testNormalTtlQueueName = "test_ttl_queue";

    public static final String testDeadLetterExchangeName = "test_dead_letter_exchange";
    public static final String testDeadLetterRouteKey = "test_dead_letter_route";
    public static final String testDeadLetterQueueName = "test_dead_letter_queue";


    @Autowired
    private AmqpAdmin amqpAdmin;

    @Override
    public void afterPropertiesSet() throws Exception {
        // 正常交换机
        Exchange normalExchange = ExchangeBuilder.directExchange(testTtlQueueExchangeName).durable(true).build();
        amqpAdmin.declareExchange(normalExchange);

        // 死信交换机，这里用 direct 作为死信交换机
        Exchange deadLetterExchange = ExchangeBuilder.directExchange(testDeadLetterExchangeName).durable(true).build();
        amqpAdmin.declareExchange(deadLetterExchange);

        // 正常队列，设置队列的死信交换机和死信路由键，死信路由键用户匹配死信队列
        // 设置队列的 TTL 为 20s, 消息入队20s后成为死信，被路由到死信队列
        Queue normalQueue = QueueBuilder.durable(testNormalTtlQueueName)
                .deadLetterExchange(testDeadLetterExchangeName)
                .deadLetterRoutingKey(testDeadLetterRouteKey)
                .ttl(20000)
                .build();

        amqpAdmin.declareQueue(normalQueue);

        // 死信队列
        Queue deadLetterQueue = QueueBuilder.durable(testDeadLetterQueueName).build();
        amqpAdmin.declareQueue(deadLetterQueue);


        // 绑定正常交换机和正常队列
        Binding normalBinding = BindingBuilder.bind(normalQueue).to(normalExchange).with(testTtlQueueRouteKey).noargs();
        amqpAdmin.declareBinding(normalBinding);

        // 绑定 死信交换机和死信队列
        Binding deadLetterBinding = BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with(testDeadLetterRouteKey).noargs();
        amqpAdmin.declareBinding(deadLetterBinding);
    }
}
